
`include "common_header.verilog"

//  *************************************************************************
//  File : p8264_block_check82_stm.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited.
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Thomas Schrobenhauser
//  info@morethanip.com
//  *************************************************************************
//  Description : 100G Base-R PCS Receive: block decode state machine
//  Version     : $Id: p8264_block_check82_stm.v,v 1.3 2017/03/28 08:23:52 dk Exp $
//  *************************************************************************

module p8264_block_check82_stm (

   reset,
   clk,
   clk_ena,
   init_cond,
   r_type_c,
`ifdef MTIPPCS_EEE_ENA
   rx_lpi_active,
   r_type_li,
`endif
   r_type_s,
   r_type_t,
   r_type_d,
   r_type_edt_next,
   state_in,
   state_next,
   error_out,
   rx_init_out);

input   reset;                  //  asynch reset
input   clk;                    //  system clock        
input   clk_ena;                //  clock enable
input   init_cond;              //  r_test_mode + hi_ber + !align_status
input   r_type_c;               //   C Block type received
`ifdef MTIPPCS_EEE_ENA
input   rx_lpi_active;          // A Boolean variable that is set to true when the RS-FEC sublayer infers that the Low Power Idle is
                                // being received from the link partner and is set to false otherwise.

input   r_type_li;              // LI block type received
`endif
input   r_type_s;               //   S Block type received
input   r_type_t;               //   T Block type received
input   r_type_d;               //   D Block type received
input   r_type_edt_next;        //   Next is E or D or T

`ifdef MTIPPCS_EEE_ENA
input   [2:0] state_in;         //  current state
output  [2:0] state_next;       //  next state
wire    [2:0] state_next; 
 `else
input   [1:0] state_in;         //  current state
output  [1:0] state_next;       //  next state
wire    [1:0] state_next; 
`endif

output  error_out;              //  error should be sent 
output  rx_init_out;            //  RX_INIT state => produce local fault

wire    error_out; 
wire    rx_init_out; 


`ifdef MTIPPCS_EEE_ENA
parameter RX_C_STATE  = 3'b 000;  
parameter RX_D_STATE  = 3'b 001; 
parameter RX_T_STATE  = 3'b 010; 
parameter RX_E_STATE  = 3'b 011; 
parameter RX_LI_STATE = 3'b 100;
wire    [2:0] next_rx_0;  
 `else
parameter RX_C_STATE = 2'b 00; 
parameter RX_D_STATE = 2'b 01; 
parameter RX_T_STATE = 2'b 10; 
parameter RX_E_STATE = 2'b 11; 

wire    [1:0] next_rx_0; 
`endif

wire    next_rx_e_0; 
reg     rx_init; 

//  Init state - async assert but deassert aligned.
// =====================================================================

always @(posedge clk or posedge reset)
   begin : p_init
   if (reset == 1'b 1)
      begin
      rx_init <= 1'b 1;	
      end
   else
      begin
      if (clk_ena == 1'b 1)
         begin
         rx_init <= init_cond;	
         end
      else if( init_cond == 1'b 1 )     // async assert in case clk_ena stops
         begin
         rx_init <= 1'b 1;	
         end
      end
   end

//  STM
//  ---
assign next_rx_0 =(rx_init == 1'b 1 & r_type_c == 1'b 1 | 
                   state_in == RX_T_STATE & r_type_c == 1'b 1 | 
                   state_in == RX_E_STATE & r_type_c == 1'b 1 | 
                   state_in == RX_C_STATE & r_type_c == 1'b 1
`ifdef MTIPPCS_EEE_ENA
                                                              |
                   state_in == RX_LI_STATE & r_type_c == 1'b 1 & rx_lpi_active != 1'b 1
`endif                                      
                   ) ? RX_C_STATE : 
                   
                  (rx_init == 1'b 1 & r_type_s == 1'b 1 | 
                   state_in == RX_C_STATE & r_type_s == 1'b 1 | 
                   state_in == RX_T_STATE & r_type_s == 1'b 1 | 
                   state_in == RX_E_STATE & r_type_d == 1'b 1 | 
                   state_in == RX_D_STATE & r_type_d == 1'b 1) ? RX_D_STATE : 
                   
                  (state_in == RX_D_STATE & r_type_t == 1'b 1 & r_type_edt_next == 1'b 0 | 
                   state_in == RX_E_STATE & r_type_t == 1'b 1 & r_type_edt_next == 1'b 0) ? RX_T_STATE : 
`ifdef MTIPPCS_EEE_ENA
                  (state_in == RX_C_STATE & r_type_li == 1'b 1 | 
                   state_in == RX_T_STATE & r_type_li == 1'b 1 | 
                   state_in == RX_E_STATE & r_type_li == 1'b 1 |
                   state_in == RX_LI_STATE & rx_lpi_active == 1'b 1 |
                   state_in == RX_LI_STATE & r_type_li == 1'b 1) ? RX_LI_STATE :
`endif                    
                   RX_E_STATE; 

assign next_rx_e_0 = next_rx_0 == RX_E_STATE & rx_init == 1'b 0 ? 1'b 1 : 1'b 0; 

//  wire outputs
assign state_next = next_rx_0; 
assign error_out = next_rx_e_0; 
assign rx_init_out = rx_init; 

endmodule // module p8264_block_check82_stm

